package Main;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//http://www.vogella.de/articles/JavaConcurrency/article.html#concurrencyjava_synchronized

/**
 * Thread t = new Thread(new BeadThread(givenData Array));
 * t.start();
 * @authors kyle corrigan & alex roca
 */
public class BeadSort extends Derp implements Runnable{//potentially works?
  protected volatile ArrayList<ArrayList<Integer>> abacus; //declared as volatile, guarantees any thread will see the most recent value
  protected volatile ArrayList<Integer> result;
  protected int[] data;
  /**
   * Constructor
   */
  protected BeadSort(int[] givenData){
    data = givenData;
    abacus = new ArrayList<ArrayList<Integer>>();
    result = new ArrayList<Integer>();
  }//statistically what are the odds of randomly grabbing either max or min out of an array of X elements?
  public void run() {
    Thread worker;
    ExecutorService es = Executors.newCachedThreadPool();
    for(int i=0; i < data.length; i++){//SPAWN ALL THE NUMBERS!
      worker = new Thread(new Number(data[i]));
      es.execute(worker);
    }  
    es.shutdown();//wait till all number threads done
    while (!es.isTerminated()) {} //do nothing and WAIT. geez.
    //Hand Sean the uncounted abacus here!
    ExecutorService ex = Executors.newFixedThreadPool(BeadSort.this.abacus.get(0).size());
    int geo = BeadSort.this.abacus.get(0).size();
    for(int x=0; x<geo; x++){//expand the results array
      BeadSort.this.result.add(0);
    }
    for(int y=0; y < geo; y++){//SPAWN ALL THE COUNTERS!
      worker = new Thread(new Counter(y));
      ex.execute(worker);
    }
    ex.shutdown();
    while(!ex.isTerminated()){}//again..you shall wait.
    
    Derp.sorted = result;
  }
  /**
   * the point of this class is to sum the index's of the integers in the arraylists of arraylists.
   * in other words, it counts the beads on the created poles (after the gravity which was implemented when they were added)
   */
  public class Counter implements Runnable{
    protected int loc;
    public Counter(int location){
      loc  = location;
    }
    public void run(){
      int beadCount=0;
      for(int x=0; x<BeadSort.this.abacus.size();x++){
        if(!BeadSort.this.abacus.get(x).isEmpty()){
          try{
          BeadSort.this.abacus.get(x).get(loc);
          beadCount++;}catch (IndexOutOfBoundsException t){}
        }
      }
      BeadSort.this.result.set(loc,beadCount);
    }//ends run
  }
  /**
   * the point of this class is to put the beads in the abacus
   */
  public class Number implements Runnable{
    protected int num;
    
    public Number(int size){
      num = size;
    }
    public void run() {
      for(int i = 0; i < num; i++){
        try{
          BeadSort.this.abacus.get(i).add(1);//gets the sub abacus
        }catch (IndexOutOfBoundsException r){
          BeadSort.this.abacus.add(new ArrayList<Integer>());
          BeadSort.this.abacus.get(abacus.size()-1).add(1);
        }
      }
    } 
    /*
    each number could spawn a thread(called bead) for its value
    have all beads update an appropriate index, i.e. if you were first thread you update first index, 2nd thread you update 2nd index, etc.
    */
  }
}

